import { _decorator } from 'cc';
import EventDispatcher from '../Coms/EventDispatcher';
import { JsonOb } from '../Coms/JsonOb';
import Stor from '../Managers/StorageManager';
import { puremvc } from './puremvc';
const { ccclass, property } = _decorator;
export const VMExit = "VMExit";
export const VMEnter = "VMEnter";
export type VM<T> = ViewModel<T>
class ViewModel<T> extends EventDispatcher {
    public key: string;
    private __$data: any;
    constructor(data: T, key: string, noticeSame: boolean = false) {
        super()
        let obj = { d: data };
        new JsonOb(obj, this._callback.bind(this), noticeSame);
        this.key = key;
        this.__$data = obj;
    }
    set d(val: T) {
        this.__$data.d = val;
    }
    get d() {
        return this.__$data.d;
    }
    clonePrototype() {
        let dataProto = Object.getPrototypeOf(this.__$data);
        if (dataProto) {
            let selfProto = Object.getPrototypeOf(this);
            setPrototypeRecursively(this.__$data, selfProto);
            Object.setPrototypeOf(this, Object.getPrototypeOf(this.__$data));
        }
        Object.keys(this.__$data).forEach((key) => {
            let self = this;
            Object.defineProperty(self, key, {
                get: function () {
                    return this.__$data[key];
                },
                set: function (newVal) {
                    this.__$data[key] = newVal;
                }
            });
        }, this);
    }
    // 回调函数 请注意 回调的 path 数组是 引用类型，禁止修改
    private _callback(n: any, o: any, path: string[]): void {
        this.emit(VMExit, o);
        this.emit(VMEnter, n);
    }
}
function setPrototypeRecursively(obj, newPrototype) {
    let currentProto = Object.getPrototypeOf(obj);
    if (currentProto == Object.prototype) {
        Object.setPrototypeOf(obj, newPrototype);
    }
    else if (currentProto == null) {
        Object.setPrototypeOf(obj, newPrototype);
    }
    else if (currentProto == newPrototype) {
        return;
    }
    else {
        setPrototypeRecursively(currentProto, newPrototype);
    }
}
export function vm<T>(data: T, key: string, noticeSame = false) {
    let ob = new ViewModel(data, key, noticeSame);
    ob.clonePrototype();
    return ob as VM<T>;
}
export function saveVm<T>(data: T, storKey: string, noticeSame = false) {
    let saveData = Stor.Get(storKey, data);
    let v = vm(saveData, storKey, noticeSame);
    v.on(VMEnter, () => Stor.Set(storKey, v.d), v);
    return v;
}
@ccclass('BaseModel')
export class BaseModel extends puremvc.Proxy {

}


